package cn.ycc1.baseset.classes;

import java.time.DayOfWeek;

/**
 * Enums
 * @author ycc
 * @date 2025/3/4
 * What are enums?
 * Enums are classes where all instances are known to the compiler. They are used for creating types that can only have few possible values.
 *
 * Enums can be created similar to classes but use the enum keyword instead of class. In the body, there is a list of instances of the enum called enum constants which are seperated by ,. No instances of the enum can be created outside of enum constants.
 *
 * public enum DayOfWeek {
 *     // enum constants are listed here:
 *     MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
 * }
 * All enums implicitly extend java.lang.Enum and cannot have any subclasses.
 *
 */
public class Enums {
    /**
     * Accessing, evaluating, and comparing enums
     */


//    DayOfWeek someDay = DayOfWeek.FRIDAY;
//
//    switch (someDay) {
//        case MONDAY ->
//                System.out.println("The week just started.");
//        case TUESDAY, WEDNESDAY, THURSDAY ->
//                System.out.println("We are somewhere in the middle of the week.");
//        case FRIDAY ->
//                System.out.println("The weekend is near.");
//        case SATURDAY, SUNDAY ->
//                System.out.println("Weekend");
//        default ->
//                throw new AssertionError("Should not happen");
//    }

    /**
     * Adding members to enums
     * Just like classes, enums can have constructors, methods and fields. In order to add these,
     * it is necessary to add a ; after the list of enum constants. Arguments to the constructor
     * are passed in parenthesis after the declaration of the enum constant.
     */
    public enum DayOfWeek {
        MONDAY("MON"), TUESDAY("TUE"), WEDNESDAY("WED"), THURSDAY("THU"), FRIDAY("FRI"), SATURDAY("SAT"), SUNDAY("SUN");

        private final String abbreviation;

        DayOfWeek(String abbreviation) {
            this.abbreviation = abbreviation;
        }

        public String getAbbreviation() {
            return abbreviation;
        }
    }

    /**
     * Special methods
     * All enums have a few methods that are added implicitly.
     *
     * For example, the method name() is present in all enum instances and can be used to get the name of the enum constant.
     * Similarly, a method named ordinal() returns the position of the enum constant in the declaration.
     *
     * System.out.println(DayOfWeek.MONDAY.name());    // prints "MONDAY"
     * System.out.println(DayOfWeek.MONDAY.ordinal()); // prints "0" because MONDAY is the first constant in the DayOfWeek enum
     * Aside from instance methods, there are also static methods added to all enums. The method values() returns an
     * array containing all instances of the enum and the method valueOf(String) can be used to get a specific instance by its name.
     *
     * DayOfWeek[] days = DayOfWeek.values(); // all days of the week
     * DayOfWeek monday = DayOfWeek.valueOf("MONDAY");
     * Furthermore, enums implement the interface Comparable. By default, enums are ordered according to their ordinal
     * number i.e. in the order of occurrence of the enum constant. This allows for comparing instances of enums
     * as well as sorting or searching.
     *
     * public void compareDayOfWeek(DayOfWeek dayOfWeek){
     *     int comparison = dayOfWeek.compareTo(DayOfWeek.WEDNESDAY);
     *     if (comparison < 0) {
     *         System.out.println("It's before the middle of the work week.");
     *     } else if (comparison > 0){
     *         System.out.println("It's after the middle of the work week.");
     *     } else {
     *         System.out.println("It's the middle of the work week.");
     *     }
     * }
     * List<DayOfWeek> days = new ArrayList<>(List.of(DayOfWeek.FRIDAY, DayOfWeek.TUESDAY, DayOfWeek.SATURDAY));
     * Collections.sort(days);
     */

    /**
     * Using enums as singletons
     * Since enums can only have a specific number of instances, it is possible to create a singleton by
     * creating an enum with only a single enum constant.
     */
    public enum SomeSingleton {
        INSTANCE;
        //fields, methods, etc.
    }

    /**
     * Abstract methods in enums
     * Even though enums cannot be extended, they can still have abstract methods.
     * In that case, an implementation must be present in each enum constant.
     */
    enum MyEnum {
        A() {
            @Override
            void doSomething() {
                System.out.println("a");
            }
        },
        B() {
            @Override
            void doSomething() {
                System.out.println("b");
            }
        };

        abstract void doSomething();
    }

}
